#include "res/res_font.h"
#include "frame.h"
#include "render/r_frustum.h"
#include "file/f_stream.h"
#include "projection.h"

#include "tex/tex_png.h"
#include "tex/tex_bmp.h"
#include "tex/tex_jpeg.h"
#include "tex/tex_dds.h"

#include "timer.h"

#include "material.h"

#include "particle_sys.h"

#include <list>
#include <vector>

#define MOVE_SPEED	0.1f

G3::FONT Font1;
G3::TEXTBOX TextBox, TextBox2;
G3::FPS_COUNTER FPSCounter;
G3::TIMER MovementTimer;
G3::PARTICLE_SYSTEM psys;
G3::COLL_MESH cmesh;
G3::COLL_POLYGON3F cp;
G3::COLL_MATERIAL cmat;

G3::FRAME frame (640, 480, 24, 0);

void PARTUpdateHandler (G3::INPUT *Input, float aElapsedTime) {
	if (Input->Keyboard.IsKeyDown (SDLK_a))
		Input->Frame->Renderer.Camera.Move (G3::VEC3F (0.0f, 1.0f, 0.0f) * aElapsedTime);
	if (Input->Keyboard.IsKeyDown (SDLK_z))
		Input->Frame->Renderer.Camera.Move (G3::VEC3F (0.0f, -1.0f, 0.0f) * aElapsedTime);
	if (Input->Keyboard.IsKeyDown (SDLK_LEFT))
		Input->Frame->Renderer.Camera.Move (G3::VEC3F (-1.0f, 0.0f, 0.0f) * aElapsedTime);
	if (Input->Keyboard.IsKeyDown (SDLK_RIGHT))
		Input->Frame->Renderer.Camera.Move (G3::VEC3F (1.0f, 0.0f, 0.0f) * aElapsedTime);
	if (Input->Keyboard.IsKeyDown (SDLK_UP))
		Input->Frame->Renderer.Camera.Move (G3::VEC3F (0.0f, 0.0f, 1.0f) * aElapsedTime);
	if (Input->Keyboard.IsKeyDown (SDLK_DOWN))
		Input->Frame->Renderer.Camera.Move (G3::VEC3F (0.0f, 0.0f,-1.0f) * aElapsedTime);
	if (Input->Keyboard.IsKeyDown (SDLK_s))
		cmesh.Materials [0].Type = G3::GCT_STICK;
	if (Input->Keyboard.IsKeyDown (SDLK_b))
		cmesh.Materials [0].Type = G3::GCT_BOUNCE;
	if (Input->Keyboard.IsKeyDown (SDLK_r))
		cmesh.Materials [0].Type = G3::GCT_RECYCLE;

	if (Input->Keyboard.IsKeyDown (SDLK_ESCAPE))
		Input->SendQuit ();
}

int main (int argc, char **argv) {
	frame.Create ("Game3ngine");

	frame.Renderer.Create ();
	frame.Renderer.SetPerspective (640, 480);

	frame.Input.Mouse.SetMode (MOUSE_CENTER);

	frame.Input.doOnUpdate (PARTUpdateHandler);

    /* Enable smooth shading */
    glShadeModel( GL_SMOOTH );

    /* Set the background black */
    glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );

    /* Depth buffer setup */
    glClearDepth( 1.0f );

    /* The Type Of Depth Test To Do */
    glDepthFunc( GL_LEQUAL );

    /* Enable 2D Texture Mapping */
    glEnable( GL_TEXTURE_2D );

	G3::MainFilesys.MountDir ("../../media", "");
	G3::MainFilesys.MountDir ("../../media/font", "");

	Font1.Load ("font.lua");

	TextBox.Font = &Font1;
	TextBox2.Font = &Font1;
	TextBox.Position = G3::VEC2I (10, 10);
	TextBox2.Position = G3::VEC2I (10, 22);

	cmesh.Vertices.push_back (G3::VEC3F (-5, 0, -5));
	cmesh.Vertices.push_back (G3::VEC3F ( 5, 0, -5));
	cmesh.Vertices.push_back (G3::VEC3F ( 5, 0,  5));
	cmesh.Vertices.push_back (G3::VEC3F (-5, 0,  5));

	cmat.Elasticity = 1.0f;
	cmat.Type = G3::GCT_BOUNCE;
	cmesh.Materials.push_back (cmat);

	Assert (!cmesh.Materials.empty (), "Vector push_back failed");

	cp.MaterialID = 0;
	cp.Vertices.push_back (2);
	cp.Vertices.push_back (1);
	cp.Vertices.push_back (0);
	cmesh.Polygons.push_back (cp);
	cp.Clear ();
	cp.Vertices.push_back (3);
	cp.Vertices.push_back (2);
	cp.Vertices.push_back (0);
	cmesh.Polygons.push_back (cp);
	cmesh.CalcPlanes ();

	psys.CollGeom = &cmesh;
	psys.Load ("particle_systems/fountain.lua");
	psys.Init ();

	FPSCounter.Start ();
	MovementTimer.Start ();

	while (true) {
		frame.Input.GetInput ();

        frame.Renderer.ClearBuffer ();

		FPSCounter.CheckTime ();
		psys.Update (frame.Input.GetElapsedTime ());

        frame.Renderer.Look ();
            frame.Renderer.RenderGrid ();

        cmesh.Render ();

		glColor3f (1, 1, 1);

		glEnable (GL_TEXTURE_2D);

		psys.Render ();

		TextBox.glPrint ("FPS: %lf", FPSCounter.FPS);

		if (cmesh.Materials [0].Type == G3::GCT_STICK)
			TextBox2.glPrint ("[S] - Stick B - Bounce R - Recycle");
		if (cmesh.Materials [0].Type == G3::GCT_BOUNCE)
			TextBox2.glPrint ("S - Stick [B] - Bounce R - Recycle");
		if (cmesh.Materials [0].Type == G3::GCT_RECYCLE)
			TextBox2.glPrint ("S - Stick B - Bounce [R] - Recycle");

        frame.Renderer.SwapBuffer ();

		FPSCounter.AddFrame ();
	}

	return 0;
}

